
# ifndef __VECTOR3_H__
# define __VECTOR3_H__

# include "dfxCore.h"

namespace DFX
{
    class DFX_EXPORT Vector3
    {
    public:

        Float32 X, Y, Z;

    public:

        Vector3(Float32 f = 0.0f)
            : X(f), Y(f), Z(f)
        {
        }

        Vector3(Float32 x, Float32 y, Float32 z)
            : X(x), Y(y), Z(z)
        {
        }

        Vector3(const Vector3 &v)
            : X(v.X), Y(v.Y), Z(v.Z)
        {
        }

        inline void Set(Float32 x, Float32 y, Float32 z)
        {
            X = x;
            Y = y;
            Z = z;
        }

        inline Float32 GetLengthSqr() const
        {
            return X * X + Y * Y + Z * Z;
        }

        inline Float32 GetLength() const
        {
            return sqrtf(X * X + Y * Y + Z * Z);
        }

        inline Float32 Dot(const Vector3 &v) const
        {
            return X * v.X + Y * v.Y + Z * v.Z;
        }

        inline Vector3 Cross(const Vector3 &v) const
        {
            return Vector3(Y * v.Z - Z * v.Y,
                           Z * v.X - X * v.Z,
                           X * v.Y - Y * v.X);
        }

        inline void Normalize()
        {
            Float32 length = sqrtf(X * X + Y * Y + Z * Z);

            if (length != 0.0f)
            {
                Float32 invLen = 1.0f / length;

                X *= invLen;
                Y *= invLen;
                Z *= invLen;
            }
        }

        Float32& operator [] (unsigned int i)
        {
            return (&X)[i];
        }

        const Float32& operator [] (unsigned int i) const
        {
            return (&X)[i];
        }

        inline Vector3 operator + (const Vector3 &v) const
        {
            return Vector3(X + v.X, Y + v.Y, Z + v.Z);
        }

        inline Vector3 operator - (const Vector3 &v) const
        {
            return Vector3(X - v.X, Y - v.Y, Z - v.Z);
        }

        inline Vector3 operator * (float f) const
        {
            return Vector3(X * f, Y * f, Z * f);
        }

        inline Vector3 operator / (float f) const
        {
            return Vector3(X / f, Y / f, Z / f);
        }

        inline Vector3& operator += (const Vector3 &v)
        {
            X += v.X;
            Y += v.Y;
            Z += v.Z;

            return *this;
        }

        inline Vector3& operator -= (const Vector3 &v)
        {
            X -= v.X;
            Y -= v.Y;
            Z -= v.Z;

            return *this;
        }

        inline Vector3& operator *= (float f)
        {
            X *= f;
            Y *= f;
            Z *= f;

            return *this;
        }

        inline bool operator == (const Vector3 &v) const
        {
            return X == v.X && Y == v.Y && Z == v.Z;
        }

        inline bool operator != (const Vector3 &v) const
        {
            return X != v.X || Y != v.Y || Z != v.Z;
        }
    };
}

# endif